// filepath: d:\hello\HelloQtOpenGL\main.cpp
#include <QApplication>
#include <QOpenGLWidget>
#include <QSurfaceFormat>
#include <QOpenGLFunctions_3_3_Core>
#include <QOpenGLShaderProgram>
#include <QOpenGLBuffer>
#include <QOpenGLVertexArrayObject>
#include <QDebug>

class OpenGLWidget : public QOpenGLWidget, protected QOpenGLFunctions_3_3_Core {
    QOpenGLShaderProgram *program;
    QOpenGLBuffer vbo;
    QOpenGLVertexArrayObject vao;

public:
    OpenGLWidget(QWidget *parent = nullptr) : QOpenGLWidget(parent), program(nullptr) {}
    ~OpenGLWidget() {
        if (context() && context()->isValid()) {
            makeCurrent();
            vao.destroy();
            vbo.destroy();
            delete program;
            doneCurrent();
        }
    }

protected:
    void initializeGL() override {
        initializeOpenGLFunctions();
        glClearColor(1.0f, 1.0f, 1.0f, 1.0f); // 设置背景颜色为白色

        // 创建着色器程序
        program = new QOpenGLShaderProgram(this);
        program->addShaderFromSourceCode(QOpenGLShader::Vertex,
            "#version 330 core\n"
            "layout (location = 0) in vec2 aPos;\n"
            "void main() {\n"
            "   gl_Position = vec4(aPos, 0.0, 1.0);\n"
            "}\n"
        );
        program->addShaderFromSourceCode(QOpenGLShader::Fragment,
            "#version 330 core\n"
            "out vec4 FragColor;\n"
            "uniform bool isBorder;\n"
            "void main() {\n"
            "   if (isBorder) {\n"
            "       FragColor = vec4(0.0, 0.0, 0.0, 1.0); // Border color: black\n"
            "   } else {\n"
            "       FragColor = vec4(1.0, 0.0, 0.0, 1.0); // Fill color: red\n"
            "   }\n"
            "}\n"
        );
        program->link();

        // 检查着色器是否编译成功
        if (!program->isLinked()) {
            qDebug() << "Shader program linking failed:" << program->log();
            return;
        }

        // 创建 VAO 和 VBO
        vao.create();
        vao.bind();
        vbo.create();
        vbo.bind();

        // 设置顶点属性指针
        glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), (void*)0);
        glEnableVertexAttribArray(0);

        vao.release();
        vbo.release();
    }

    void resizeGL(int w, int h) override {
        glViewport(0, 0, w, h); // 设置视口

        // 指定宽度和高度（以像素为单位）
        float rect_width = 20.0f;  // 宽度（像素）
        float rect_height = rect_width * 5.0f;  // 高度为宽度的 5 倍

        // 将像素值转换为裁剪空间坐标
        float x_clip = rect_width / w * 2.0f;  // 转换为裁剪空间
        float y_clip = rect_height / h * 2.0f;  // 转换为裁剪空间

        // 定义顶点数据（填充的长方形 + 边框）
        const GLfloat vertices[] = {
            // 填充的长方形
            -x_clip / 2.0f, -y_clip / 2.0f, // 左下角
             x_clip / 2.0f, -y_clip / 2.0f, // 右下角
            -x_clip / 2.0f,  y_clip / 2.0f, // 左上角
             x_clip / 2.0f,  y_clip / 2.0f, // 右上角

            // 边框的长方形
            -x_clip / 2.0f, -y_clip / 2.0f, // 左下角
             x_clip / 2.0f, -y_clip / 2.0f, // 右下角
             x_clip / 2.0f,  y_clip / 2.0f, // 右上角
            -x_clip / 2.0f,  y_clip / 2.0f  // 左上角
        };

        // 更新 VBO 数据
        vbo.bind();
        vbo.allocate(vertices, sizeof(vertices));
        vbo.release();

        // 重新绑定顶点属性
        vao.bind();
        vbo.bind();
        glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), (void*)0);
        glEnableVertexAttribArray(0);
        vao.release();
        vbo.release();
    }

    void paintGL() override {
        glClear(GL_COLOR_BUFFER_BIT); // 清除颜色缓冲区

        // 绑定着色器程序和 VAO
        program->bind();
        vao.bind();

        // 绘制填充的长方形
        program->setUniformValue("isBorder", false);
        glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

        // 绘制边框
        program->setUniformValue("isBorder", true);
        glEnable(GL_LINE_SMOOTH); // 启用抗锯齿
        glLineWidth(1.0f); // 设置边框宽度为 1 像素
        glDrawArrays(GL_LINE_LOOP, 4, 4);

        vao.release();
        program->release();

        // 检查 OpenGL 错误
        GLenum err;
        while ((err = glGetError()) != GL_NO_ERROR) {
            qDebug() << "OpenGL error in paintGL:" << err;
        }
    }
};

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);

    // 设置 OpenGL 格式
    QSurfaceFormat format;
    format.setVersion(3, 3); // 使用 OpenGL 3.3
    format.setProfile(QSurfaceFormat::CoreProfile); // 核心模式
    QSurfaceFormat::setDefaultFormat(format);

    // 创建 OpenGL 窗口
    OpenGLWidget widget;
    widget.resize(800, 600); // 设置窗口大小
    widget.show();

    return app.exec();
}